#include "tcptransport.h"
namespace apollo
{
	namespace core
	{
		TcpTransport::TcpTransport(QObject *parent)
			: QThread(parent)
		{

		}

		TcpTransport::~TcpTransport()
		{
			if(socket.isNull() == false && socket->isOpen())
			{

				socket->disconnectFromHost();
			}
		}

		void TcpTransport::run()
		{

			socket = QSharedPointer<QTcpSocket>(new QTcpSocket);
			connect(socket.data(), SIGNAL(readyRead()), this, SLOT(readDataHandler()));
			connect(socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketErrorHandler(QAbstractSocket::SocketError)));


			this->exec();

		}

		void TcpTransport::readDataHandler()
		{

			while(socket->isValid() && socket->bytesAvailable() > 0)
			{

				PayloadPtr payload = format.unblockingRead(socket.dynamicCast<QAbstractSocket>(), ctx);
				if(ctx.state == WireFormat::Successful)
				{
					emit dataArrivedEvent(payload);
				}
				else if(ctx.state == WireFormat::MessageSizeError)
				{
					socket->abort();
					//TODO: handle error
					break;
				}
				else if(ctx.state == WireFormat::ChecksumError)
				{
					socket->abort();
					//TODO: ...
				}
				else if(ctx.state == WireFormat::NoAvailabeBytesError)
				{
					return;
				}
			}
		}


		void TcpTransport::socketErrorHandler(QAbstractSocket::SocketError socketError)
		{
			emit errorEvent(socket->peerAddress().toString(), socket->peerPort(),  socketError);

			this->exit();
		}

		void TcpTransport::customEvent(QEvent *event)
		{
			AnyEvent * anyEvent = dynamic_cast<AnyEvent *>(event);
			if(anyEvent != NULL)
			{

				socket->write(anyEvent->getData(), anyEvent->getSize());
			}
			else 
			{
				//std::cout << "received event that is not AnyEvent" << std::endl;
			}


		}


	}}
